/************************************************************************/
/*    Author: Scott Bevin                                               */
/************************************************************************/

#pragma once

#include <list>
#include <vector>
#include <algorithm>

#include "../Body.h"
#include "../AABB.h"

namespace XF
{
	class OctTreeNode
	{
	private:
		unsigned int mTargetObjects;
		unsigned int mMaxDepth;

		std::list<Body*> mObjects;

		OctTreeNode *mParentNode;
		std::vector<OctTreeNode*> mChildNodes;

		AABB mAABB;
		unsigned int mDepth;

			/**
			attempts to place the object into the proper node from this point downwards, 
			this function is not capable of propagating upwards through the tree.
			*/
		bool PlaceBodyIntoNode(Body* body);

		/**
			spawns 8 children node
			*/
		void SplitNode();

		/**
			deletes all the children of this node
			*/
		void DeleteChildNodes();

	public:
		OctTreeNode(OctTreeNode &copyNode);
		OctTreeNode(OctTreeNode *parent, int depth, float x, float y, float z, float w, float h, float d);
		~OctTreeNode();


		/**
			this function will add an object into the tree, subdividing if necessary and possible
			*/
		bool AddBody(Body* body);

		/**
			remove object will remove an object and unnecessary nodes
			*/
		bool RemoveBody(Body* body);

		/**
			counts the number of objects held by the tree from this node downwards
		*/
		int GetNoOfObjects();

		int GetNoOfObjectsThisNodeHolds(){ return (int)mObjects.size(); }

		bool IsRootNode(){ return (mParentNode == NULL); }

		bool HasChildNodes() { return mChildNodes[0] != NULL; }
		std::vector<OctTreeNode*> GetChildNodes(){return std::vector<OctTreeNode*>(mChildNodes);}

		int TargetObjects(){ return mTargetObjects; }
		void TargetObjects(int targetObjects){ mTargetObjects = targetObjects; }

		int MaxDepth(){ return mMaxDepth; }
		void MaxDepth(int maxDepth){ mMaxDepth = maxDepth; }
	};
}